#include "inc.h"
#include "tokenizer.h"
#include "parser.h"
#include "executor.h"

#define MAX_INPUT_SIZE 200

static int readInput(char *input);
static void cleanStdinBuf(int is_clean_stdin_buf);

int main()
{
    char input_buf[MAX_INPUT_SIZE];
    db_t *db = createDB();

    while (1) {
        printf("BookDB > "); 
        fflush(stdout);

        int is_clean_stdin_buf = readInput(input_buf);
        // printf("input: ~ %s ~\n", input_buf);
        cleanStdinBuf(is_clean_stdin_buf);

        if (input_buf[0] == '\0') {
            continue;
        } else if (input_buf[0] == '.') {
            execute(db, NULL, input_buf, 1);
        } else {
            int index = 0;
            int last_index = 0;
            ASTNode *ast_node;
            ast_node = parseSQL(input_buf, &index, &last_index);
            if (ast_node == NULL) continue;

            PlanNode *plan_node;
            plan_node = buildPlanTree(ast_node);

            execute(db, plan_node, NULL, 0);

            destroyAST(ast_node);
            destroyPlanTree(plan_node);
        }
    }
    exit(EXIT_SUCCESS);
}

static int readInput(char *input_buf)
{
    /*
     * Meta command doesn't end with semicon
     * Sql statement end with semicon
     */

    int input_len = 0;
    int is_skip_space = 1;
    int is_meta_cmd = 0;
    int is_clean_stdin_buf = 0;
    char c;

    while (1) {
        if (input_len >= MAX_INPUT_SIZE) {
            input_buf[MAX_INPUT_SIZE - 1] = '\0';
            return 0;
        }

        while (is_skip_space) {
            c = getchar();    
            if (isalpha(c)) {
                is_skip_space = 0;
                is_meta_cmd = 0;
                input_buf[input_len++] = c;
            } else if (c == '.') {
                is_skip_space = 0;
                is_meta_cmd = 1;
                input_buf[input_len++] = c;
            } else if (c == '\n') {
                input_buf[input_len] = '\0';
                is_clean_stdin_buf = 0;
                return is_clean_stdin_buf;
            }
        }

        c = getchar();
        if (is_meta_cmd) {
            if (c == '\n') {
                input_buf[input_len] = '\0';
                break;
            } else 
                input_buf[input_len++] = c;
        } else {
            if (c == ';') {
                input_buf[input_len] = '\0';
                is_clean_stdin_buf = 1;
                break;
            } else if (c == '\n') {
                printf("   ... > "); 
                fflush(stdout);
                input_buf[input_len++] = ' ';
            } else {
                input_buf[input_len++] = c;
            }
        }
    }

    return is_clean_stdin_buf;
}

static void cleanStdinBuf(int is_clean_stdin_buf)
{
    while (is_clean_stdin_buf && getchar() != '\n');  /* Clean the input buffer */
}